<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>[1.17]-日记纪录：简化版的日记接口 | PhalApi(π框架) - PHP轻量级开源接口框架 - 助你创造价值！</title>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <meta content="yes" name="apple-mobile-web-app-capable">
    <meta content="black" name="apple-mobile-web-app-status-bar-style">
    <meta content="telephone=no" name="format-detection">
    <meta content="email=no" name="format-detection">
    <meta name="Author" content="PhalApi,ecitlm,dogstar">
    <meta name="description" content="[1.17]-日记纪录：简化版的日记接口，PhalApi是一个PHP轻量级开源接口框架，致力于快速开发接口服务。支持HTTP/SOAP/RPC等协议，可用于搭建接口/微服务/RESTful接口/Web Services。我们不断更新，保持生气；为接口负责，为开源负责！并承诺永久免费！">
    <meta name="keywords" content="PhalApi,phalapi,phalapi接口开发,后台接口开发,后台接口开发框架,接口开发,接口框架,开源接口框架,PHP后台接口开发,PHP接口开发,PHP接口框架,PHP后台接口框架,phalapi官网,PHP接口框架,php接口开发框架,php接口开发,php web框架,π框架,π开发框架,π接口框架,π接口开发框架,api接口,php接口,,PHP接口框架,phalapi文档,phalapi wiki,PhalApi文档,phalapi在线文档,phalapi官方文档">

    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" media="screen">
    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.css" media="screen">
    <link rel="stylesheet" href="../css/main.css" />
    <link rel="stylesheet" href="../css/loading_bar.css" />
    <link rel="icon" href="http://webtools.qiniudn.com/dog_catch.png" type="image/x-icon" />
    <script src="../js/pace.min.js"></script>
	
	<!-- 代码高亮 -->
	<link rel="stylesheet" href="../css/highlight.min.css">
	<script src="../js/highlight.min.js"></script>
	<script>hljs.initHighlightingOnLoad();</script>
    
</head>

<body>
    <!-- navbar start -->
    <div class="navbar navbar-default navbar-fixed-top" id="mainnav" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand website_name" href="/"><!-- <span>PhalApi</span> --><strong>PhalApi</strong></a>
            </div>
            <div class="navbar-collapse collapse" aria-expanded="false" style="height: 1px;">
                <ul class="nav navbar-nav navbar-right" id="nav_bar">
                    <li><a href="/"><span class="glyphicon glyphicon-home"></span></a></li>
                    <li><a href="http://qa.phalapi.net/">社区</a></li>
                    <li><a href="/download.html">下载</a></li>
                    <li class="active"><a href="/wikis/">文档</a></li>
                    <li><a href="http://www.ituring.com.cn/book/2405">书籍</a></li>
                    <li><a href="http://demo.phalapi.net/">体验</a></li>
                    <li><a href="/about.html">关于</a></li>
                    <li><a href="/donate.html">贡献</a></li>
                    <li><a href="/wikis/en/">English</a></li>
                </ul>
            </div>
            <!--/.nav-collapse -->
        </div>
    </div>
    <!-- navbar end -->


    <div id="content">
        <div class="container">
            <div class="row row-md-flex row-md-flex-wrap">
                <h4><a href="/wikis/%5B1.16%5D-%E9%85%8D%E7%BD%AE%E8%AF%BB%E5%8F%96%EF%BC%9A%E5%86%85%E5%A4%96%E7%BD%91%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E7%9A%84%E5%AE%8C%E7%BE%8E%E5%88%87%E6%8D%A2.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="/wikis/%5B1.18%5D-%E5%BF%AB%E9%80%9F%E5%87%BD%E6%95%B0%EF%BC%9A%E4%BA%BA%E6%80%A7%E5%8C%96%E7%9A%84%E5%85%B3%E6%80%80.html">下一章</a></h4>
<hr />
<h2>PHP日记接口规范</h2>
<p>关于日记系统，PHP规范给出了相当好的说明和定义，请见： <a href="http://www.php-fig.org/psr/psr-3/">Logger Interface</a>  </p>
<p><img src="http://webtools.qiniudn.com/20150411005257_2caf170c179348eca546ba5332837d09" alt="apic" />  </p>
<h2>1.17.1 简化版</h2>
<p>但在用过这么多开源框架进行各种项目开发，以及内部框架的开发后，发现实际上日记的分类并没有使用得这么丰富，而通常只是频繁地几类。因此，为了减少不必要的复杂性，这里特地精简为三种，只有：</p>
<ul>
<li>error 系统异常类</li>
<li>info 业务纪录类</li>
<li>debug 开发调试类</li>
</ul>
<p>现分说如下。</p>
<h3>(1)error 系统异常类</h3>
<p>此类是后台开发同学认为 <strong>不应该发生却发生的事情 </strong> ，即我们通常所说的系统异常。<br />
如：调用app store支付的接口失败了，我们需要纪录一下当时的场景，以便复查和给用户补尝其损失。<br />
又如：写入一条纪录到数据纪录，但失败了，我们需要纪录一下，以便排查。  </p>
<p>用法很简单，如：</p>
<pre><code class="language-php">//只有描述
DI()-&gt;logger-&gt;error('fail to insert DB');

//描述 + 简单的信息
DI()-&gt;logger-&gt;error('fail to insert DB', 'try to register user dogstar');

//描述 + 当时的上下文数据
$data = array('name' =&gt; 'dogstar', 'password' =&gt; '123456');
DI()-&gt;logger-&gt;error('fail to insert DB', $data);</code></pre>
<p>上面三条纪录，效果类如：</p>
<pre><code class="language-php">dogstar@ubuntu:dev.phalapi.com$ tailf ./Runtime/log/201502/20150207.log 
2015-02-07 20:37:55|ERROR|fail to insert DB
2015-02-07 20:37:55|ERROR|fail to insert DB|try to register user dogstar
2015-02-07 20:37:55|ERROR|fail to insert DB|{"name":"dogstar","password":"123456"}</code></pre>
<p>截图效果：
<img src="http://webtools.qiniudn.com/20150411005257_37a0566c79a78c8958d8d00a83c7f840" alt="apic" />  </p>
<h3>(2)info 业务纪录类</h3>
<p>此类通常为业务需要进行必要的操作纪录，以便发生系统问题后的回滚处理、问题排查以及数据统计。<br />
如在有缓存的情况下，可能数据没及时写入数据库而导致数据丢失或者回档，这里可以通过日记简单查看是否可以恢复。以及说明一下操作发生的背景或原由，如通常游戏中用户的经验值添加：  </p>
<pre><code class="language-php">//假设：10 + 2 = 12
DI()-&gt;logger-&gt;info('add user exp', array('name' =&gt; 'dogstar', 'before' =&gt; 10, 'addExp' =&gt; 2, 'after' =&gt; 12, 'reason' =&gt; 'help one more phper'));

//对应的LOG
2015-02-07 20:48:51|INFO|add user exp|{"name":"dogstar","before":10,"addExp":2,"after":12,"reason":"help one more phper"}</code></pre>
<p>但当哪天我们看到以下的LOG是就会发现系统存在隐藏的BUG：  </p>
<pre><code class="language-php">//WTF? 10 + 2 = 11 ???
2015-02-07 20:48:51|INFO|add user exp|{"name":"dogstar","before":10,"addExp":2,"after":11,"reason":"help one more phper"}</code></pre>
<p>而当用户玩家来投诉客服时，客服妹子来找到我们后台开发时，我们可以证明得了是系统原因造成了用户丢失1点经验值。<br />
特别地，若我们看到以下的LOG时，不难看出有人在用非法的渠道刷经验：</p>
<pre><code class="language-php">2015-02-07 20:52:35|INFO|add user exp|{"name":"dogstar","before":10,"addExp":2,"after":12,"reason":"help one more phper"}
2015-02-07 20:52:35|INFO|add user exp|{"name":"dogstar","before":12,"addExp":2,"after":14,"reason":"help one more phper"}

....

2015-02-07 20:52:35|INFO|add user exp|{"name":"dogstar","before":998,"addExp":2,"after":1000,"reason":"help one more phper"}</code></pre>
<p>所幸我们有日记并及时发现了，随后如何处理就视具体的项目而定了。但当产品来追问时，我们可以及时给出反馈和做出处理。  </p>
<p>还有更为重要的是 <strong>数据统计</strong> 。这块就App数据分析和统计这块已经有了很好的第三方服务支持，一如：友盟。但我们仍然可以轻松实现自己的数据统计，以便二次确认和定制化。毕竟，总是依赖第三方不是那么轻便，而且存在敏感数据安全问题。<br />
这里简单提供一个上报接口，如：</p>
<pre><code class="language-php">    public function getRules() {
        return array(
            'report' =&gt; array(
                'username' =&gt; array('name' =&gt; 'username', 'require' =&gt; true),
                'msg' =&gt; array('name' =&gt; 'msg', 'require' =&gt; true),
            ),
        );
    }

    public function report() {
        DI()-&gt;logger-&gt;info($this-&gt;username, $this-&gt;msg);
    }
</code></pre>
<p>客户端在需要的场景，如用户打开应用，请求：</p>
<pre><code>http://dev.phalapi.com/demo/?service=DogstarTest.Report&amp;username=dogstar&amp;msg=enter%20app</code></pre>
<p>即可看到：</p>
<pre><code class="language-php">2015-02-07 21:01:13|INFO|dogstar|enter app</code></pre>
<p>到后期，若我们需要统计用户的登录情况时，可以这样统计：</p>
<pre><code class="language-php">$ cat ./Runtime/log/201502/20150207.log | grep "enter app" | awk -F '|' '{print $3}' | sort | uniq -c
     11 dogstar
      5 King
      2 Tom</code></pre>
<h3>(3)debug 开发调试类</h3>
<p>此类为开发调试用，用法如上，这里不再赘述。以下是一些简单的示例： </p>
<pre><code class="language-php">DI()-&gt;logger-&gt;debug('just for test');

DI()-&gt;logger-&gt;debug('just for test', '一些其他的描述 ...');

DI()-&gt;logger-&gt;debug('just for test', array('name' =&gt; 'dogstar', 'password' =&gt; '******'));</code></pre>
<h2>1.17.2 使用DI()-&gt;logger-&gt;log()进行更灵活的分类</h2>
<p>若上面的error/info/debug都不能满足项目的需求时，可以这样更灵活地进行日记纪录：</p>
<pre><code class="language-php">DI()-&gt;logger-&gt;log('demo', 'add user exp', array('name' =&gt; 'dogstar', 'after' =&gt; 12));
DI()-&gt;logger-&gt;log('test', 'add user exp', array('name' =&gt; 'dogstar', 'after' =&gt; 12));

//对应的日记
2015-02-07 21:13:27|DEMO|add user exp|{"name":"dogstar","before":10,"addExp":2,"after":12,"reason":"help one more phper"}
2015-02-07 21:15:39|TEST|add user exp|{"name":"dogstar","after":12}
</code></pre>
<p>注意到，DI()-&gt;logger-&gt;log()第一个参数为日记分类的名称，在写入日记时会自动转换为大写。其接口函数签名为：  </p>
<pre><code class="language-php">    /**
     * 日记纪录
     *
     * 可根据不同需要，将日记写入不同的媒介
     *
     * @param string $type 日记类型，如：info/debug/error, etc
     * @param string $msg 日记关键描述
     * @param string/array $data 场景上下文信息
     * @return NULL
     */
    abstract public function log($type, $msg, $data);</code></pre>
<h2>1.17.3 别忘记了日记的级别设置</h2>
<p>上面的三类日记分别对应的标识为：</p>
<ul>
<li>error 系统异常类：PhalApi_Logger::LOG_LEVEL_ERROR</li>
<li>info 业务纪录类：PhalApi_Logger::LOG_LEVEL_INFO</li>
<li>debug 开发调试类：PhalApi_Logger::LOG_LEVEL_DEBUG</li>
</ul>
<p>根据不同的项目在不同环境下的需要，我们可以这样有选择性地将需要的日记分类写入保存：</p>
<pre><code class="language-php">//日记纪录
DI()-&gt;logger = new PhalApi_Logger_File(API_ROOT . '/Runtime',
    PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR);</code></pre>
<p>多个日记级别需要使用或运算进行组合。</p>
<h2>1.17.4 扩展你的日记存储</h2>
<p>普遍情况下，我们认为将日记存放在文件是比较合理的，因为便于查看、管理和统计。当然，如果你的项目需要将日记纪录在数据库，也可以快速扩展实现。如实现数据库的存储思路：  </p>
<pre><code class="language-php">//$ vim ./Apps/Common/Logger/DB.php

class Common_Logger_DB extends PhalApi_Logger {

    public function log($type, $msg, $data) {
        //TODO 数据库的日记写入 ...
    } </code></pre>
<p>随后，利用DI注册一下即可：</p>
<pre><code class="language-php">//日记纪录 - DB
DI()-&gt;logger = new Common_Logger_DB($dbConfig,
    PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR);</code></pre>
<hr />
<h4><a href="/wikis/%5B1.16%5D-%E9%85%8D%E7%BD%AE%E8%AF%BB%E5%8F%96%EF%BC%9A%E5%86%85%E5%A4%96%E7%BD%91%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E7%9A%84%E5%AE%8C%E7%BE%8E%E5%88%87%E6%8D%A2.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="/wikis/%5B1.18%5D-%E5%BF%AB%E9%80%9F%E5%87%BD%E6%95%B0%EF%BC%9A%E4%BA%BA%E6%80%A7%E5%8C%96%E7%9A%84%E5%85%B3%E6%80%80.html">下一章</a></h4><div style="float: left">
<h4>
<a href="http://qa.phalapi.net/">还有疑问？欢迎到社区提问！</a>
</h4>
</div>
            </div>
        </div>
    </div>

 <!-- 广告位 -->
<div class="grid-wrapper desktop-only">
	<p align="center">
		<a href="http://7xiz2f.com1.z0.glb.clouddn.com/%E6%88%91%E7%9A%84%E5%90%8D%E5%AD%97%E5%8F%AB%EF%BC%9A%CF%80%E6%A1%86%E6%9E%B6%20-%20PhalApi%202016%E5%B9%B4%E5%BA%A6%E5%BC%80%E6%BA%90%E6%80%BB%E7%BB%93%20-%20%E5%AE%98%E6%96%B9%E5%87%BA%E5%93%81.pdf" target="blank"><img width="950" height="100" src="http://7xiz2f.com1.z0.glb.clouddn.com/ad_20170104.png"></a>
		<a href="http://www.itran.cc/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/9/69/b88bc92455dc1239f9a5bf8d72929.png"></a>
		<a href="http://web-tools.phalapi.net/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/7/d0/88f523566c482296aecc43d185ca2.png"></a>
	</p>
</div>

        <!-- footer -->
        <div class="footer">
            <div class="link container ">
                <div class=" col-xs-7 col-sm-7 col-md-7 col-lg-7 ">
                    <h3>PhalApi (π框架)</h3>
                    <p>一个轻量级PHP开源接口框架，专注于接口服务开发，支持HTTP/SOAP/RPC协议，拥有自动生成的在线文档、多种开发语言的客户端SDK包以及可重用的扩展类库，可用于快速搭建微服务、RESTful接口或Web
                        Services。</p>
                    <!-- <p>:</p> -->
                    <span>友情链接:</span>
                    <a href="https://www.phalapi.net/" target="_blank"> PhalApi </a>
                    <a href="http://www.oschina.net/" target="_blank"> 开源中国 </a>
                    <a href="https://www.itran.cc/" target="_blank">艾翻译</a>
                    <a href="http://www.phalconphp.com/en/" target="_blank">Phalcon</a>
                    <a href="https://phpunit.de/manual/3.7/zh_cn/automating-tests.html" target="_blank">PHPUnit</a>
                    <a href="http://www.thoughtworks.com/cn/" target="_blank">ThoughtWorks</a>
                    <a href="mailto:chanzonghuang@gmail.com">友链交换</a>

                </div>
                <div class=" col-xs-5 col-sm-5 col-md-5 col-lg-5 contact_us ">
                    <h3>联系我们</h3>
                    <a href="https://github.com/phalapi/phalapi"><img src="../images/github.png" alt="github" /></a>
                    <a href="http://weibo.com/p/100808d236e99beb645bfb56ed1c37dde9b8bd?k=phalapi%E5%BC%80%E6%BA%90%E6%A1%86%E6%9E%B6&from=501&_from_=huati_topic"><img src="../images/weibo.png"  alt="weibo" /></a>
                    <a href="http://7xslqv.com1.z0.glb.clouddn.com/images/1/b0/894fde762850cb11250253f7d5ede.png"><img src="../images/zfb.png"  alt="zfb" /></a>
                    <a href="https://jq.qq.com/?_wv=1027&k=4A6reum"><img src="../images/qq.png"  alt="qq" /></a>
					<a href="http://git.oschina.net/dogstar/PhalApi"><img src="../images/git-oschina.png"  alt="git-oschina" /></a>
                </div>
                <div class="cls"></div>
                <div class="text-center copy_right"> ©2015-2017 PhalApi All Rights Reserved. <a href="http://www.miitbeian.gov.cn" target="_blank">粤ICP备15028808号</a>

				<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1255326144'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s4.cnzz.com/z_stat.php%3Fid%3D1255326144%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"));</script>
                </div>
            </div>
        </div>
    </div>


    <a href="https://github.com/phalapi"><img id="gitHub_fllow" style="position: fixed; top: 0; right: 0; border: 0;z-index:9999" src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"></a>


    <script src="../js/jquery-1.11.1.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
</body>

</html>